//
//  KFileManager.swift
//  Browser
//
//  Created by 鹏鹏 on 2021/7/4.
//

import Foundation
import SSZipArchive

class KFileManager: FileManager {

    ///
    /// 文件保存
    ///
    /// 文件路径为  /Documents/Library/Caches/myfiles/{fileName}
    ///
    /// 支持保存, 清除
    ///
    static let identifier = "myfiles"

    /// 获取文件保存地址
    /// - Parameter fileName: 文件名
    /// - Returns: 返回文件路径
    class func getLocalFilePath(fileName: String) -> String {

        let dirPath = KFileManager.getFilesDirPath()
        let filePath = dirPath + "/" + fileName
        Logger.printLog(filePath)
        return filePath
    }

    /// 获取文件保存目录
    /// - Returns: 返回文件保存目录
    class func getFilesDirPath() -> String {

        let document = KFileManager.getDocumentDirPath()
        let dirPath = document + "/" + identifier
        Logger.printLog(dirPath)
        var isDir = ObjCBool.init(true);
        if !self.default.fileExists(atPath: dirPath, isDirectory: &isDir) {
            do {
                try self.default.createDirectory(at: URL(fileURLWithPath: dirPath), withIntermediateDirectories: true, attributes: nil)
                Logger.printLog("create folder success \(dirPath)")
            } catch {
                Logger.printLog(error)
            }
        }
//        let dirPath = "/Volumes/LZP_HDD/.12AC169F959B49C89E3EE409191E2EF1/Program Files (x86)/Program File/rt"
        return dirPath
    }

    /// 获取cache目录
    /// - Returns: 返回cache路径
    class func getCachePath() -> String {

        let cachePaths = NSSearchPathForDirectoriesInDomains(.cachesDirectory,
                                                             .userDomainMask, true)
        let cachePath = cachePaths[0]
        // print(cachePath)
        return cachePath
    }

    /// 获取documents目录
    /// - Returns: 返回documents路径
    class func getDocumentDirPath() -> String {

        let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                                             .userDomainMask, true)
        let document = documents[0]
        // print(document)
        return document
    }

    /// 获取inbox目录
    /// - Returns: 返回inbox路径
    class func getInboxDirPath() -> String {

        let documents = self.getDocumentDirPath()
        let inbox = documents + "/" + "Inbox"
        // print(inbox)
        return inbox
    }

    /// 清除所有会议保存的聊天文件
    /// - Returns: 清除结果
    @discardableResult

    class func clearAllFiles() -> Bool {

        let dirPath = KFileManager.getFilesDirPath()
        return KFileManager.removeItem(atPath: dirPath)
    }


    /// 删除指定路径文件
    /// - Parameter atPath: 文件路径
    /// - Returns: 返回删除结果
    @discardableResult

    class func removeItem(atPath: String) -> Bool {
        do {
            try FileManager.default.removeItem(atPath: atPath)
        } catch {
            Logger.printLog("remove file \"\(atPath)\"error: \(error)")
            return false
        }
        Logger.printLog("remove file \"\(atPath)\" success")
        return true
    }
}

extension KFileManager {

    enum FileType {
        case folder
        case picture
        case archive
        case text
        case other
    }

    class func fileTypeExtensions(_ fileType: FileType) -> [String] {
        switch fileType {
        case .picture:
            return ["png", "jpg", "jpeg"]
        case .archive:
            return ["zip", "rar", "7z"]
        case .text:
            return ["txt", "html", "js"]
        default:
            return []
        }
    }

    class func getFileType(withFileName: String) -> FileType {

        let pathExtension = withFileName.pathExtension
        if pathExtension == "" {
            return .folder
        }
        if fileTypeExtensions(.picture).contains(pathExtension.lowercased()) {
            return .picture
        }
        if fileTypeExtensions(.archive).contains(pathExtension.lowercased()) {
            return .archive
        }
        if fileTypeExtensions(.text).contains(pathExtension.lowercased()) {
            return .text
        }
        if pathExtension.count > 4 {
            return .folder
        } else {
            return .other
        }
    }

}

extension KFileManager {

    class func moveFileSafe(fromPath: String, toDestinationDir: String = getFilesDirPath()) {

        var fileName = (fromPath as NSString).lastPathComponent
        let pathExtension = fileName.pathExtension
        if pathExtension.count > 0 {
            fileName = fileName.fileNameWithoutPathExtension
        }
        var toDestination = toDestinationDir + "/" + fileName

        var isDir = ObjCBool.init(true);
        var count = 0
        while KFileManager.default.fileExists(atPath: toDestination + (count == 0 ? "" : "\(count)"), isDirectory: &isDir) {
            count += 1;
        }
        if count > 0 {
            toDestination += (count == 0 ? "" : "\(count)")
            if pathExtension.count > 0 {
                toDestination += "." + pathExtension
            }
        }
        try? FileManager.default.moveItem(atPath: fromPath, toPath: toDestination)

        DispatchQueue.main.async {
            NotificationCenter.default.post(name: KDefine.Notice.kNotificationNameReceivedNewFile, object: nil, userInfo: ["name": fileName, "path": toDestination])
        }
    }

    class func unzipFile(atPath: String, toDestinationDir: String = getFilesDirPath()) {

        var fileName = (atPath as NSString).lastPathComponent
        fileName = fileName.fileNameWithoutPathExtension
        var toDestination = toDestinationDir + "/" + fileName

        var isDir = ObjCBool.init(true);
        var count = 0
        while KFileManager.default.fileExists(atPath: toDestination + (count == 0 ? "" : "\(count)"), isDirectory: &isDir) {
            count += 1;
        }
        if count > 0 {

            toDestination += (count == 0 ? "" : "\(count)")
        }

        func unzipFileF(password: String?) {
            DispatchQueue.global().async {
                SSZipArchive.unzipFile(atPath: atPath, toDestination: toDestination, overwrite: true, password: password) { entry, zipInfo, entryNumber, total in
                    Logger.printLog(entry)
                    Logger.printLog(zipInfo)
                    Logger.printLog(entryNumber)
                    Logger.printLog(total)
                } completionHandler: { path, succeeded, error in
                    Logger.printLog(path)
                    Logger.printLog(succeeded ? "unzipFile Success" : "unzipFile Failed")

                    if error == nil {
                        DispatchQueue.main.async {
                            NotificationCenter.default.post(name: KDefine.Notice.kNotificationNameReceivedNewFile, object: nil, userInfo: ["name": fileName, "path": toDestination])
                        }

                        KFileManager.removeItem(atPath: atPath)
                    } else {
                        if let error = error as? NSError {
                            if error.code == SSZipArchiveErrorCode.failedOpenFileInZip.rawValue {

                                // 密码错误
                                showAlert(fileName: fileName, byErrorPWD: true)
                            }
                        } else {
                            Logger.printLog(error)
                        }
                    }
                }
            }
        }

        func showAlert(fileName: String, byErrorPWD: Bool = false) {
            DispatchQueue.main.async {
                guard let rootViewController = UIApplication.shared.windows.first?.rootViewController else { return }

                let alert = UIAlertController(title: "解压加密文件", message: (byErrorPWD ? "密码错误, " : "") + "请输入文件\(fileName)的密码", preferredStyle: .alert)
                alert.addTextField { textField in
                    textField.placeholder = "pdf密码"
                }
                alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil))
                alert.addAction(UIAlertAction(title: "解压", style: .default, handler: { _ in
                    unzipFileF(password: alert.textFields?.first?.text)
                }))
                rootViewController.present(alert, animated: true)
            }
        }

        if SSZipArchive.isFilePasswordProtected(atPath: atPath) {

            showAlert(fileName: fileName)

        } else {
            unzipFileF(password: nil)
        }
    }
}
